home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-13 / mg2a_src.zip / FILEIO.C < prev    next >
C/C++ Source or Header  |  1991-02-16  |  11KB  |  483 lines

  1. /*
  2.  * Name:    Mg 2a
  3.  *         MSDOS file I/O (TurboC 1.5)
  4.  */
  5. #include    "def.h"
  6. #include    <stdio.h>
  7.  
  8. #ifdef MSC
  9. #include    <dos.h>
  10. #endif /* MSC */
  11.  
  12. #ifndef F_OK
  13. #define F_OK    0
  14. #define X_OK    1
  15. #define W_OK    2
  16. #define R_OK    4
  17. #endif
  18.  
  19. #ifndef NO_DIR
  20. extern char *wdir;
  21. #endif
  22.  
  23. static    FILE    *ffp;
  24.  
  25. /*
  26.  * Open a file for reading.
  27.  */
  28. ffropen(fn)
  29. char    *fn;
  30. {
  31.     if ((ffp=fopen(fn, "rb")) == NULL)
  32.         return (FIOFNF);
  33.     return (FIOSUC);
  34. }
  35.  
  36. /*
  37.  * Open a file for writing.
  38.  * Return TRUE if all is well, and
  39.  * FALSE on error (cannot create).
  40.  */
  41. ffwopen(fn)
  42. char    *fn;
  43. {
  44.     if ((ffp=fopen(fn, "wb")) == NULL) {
  45.         ewprintf("Cannot open file for writing");
  46.         return (FIOERR);
  47.     }
  48.     return (FIOSUC);
  49. }
  50.  
  51. /*
  52.  * Close a file.
  53.  * Should look at the status.
  54.  */
  55. ffclose()
  56. {
  57.     (VOID) fclose(ffp);
  58.     return (FIOSUC);
  59. }
  60.  
  61. /*
  62.  * Write a line to the already
  63.  * opened file. The "buf" points to the
  64.  * buffer, and the "nbuf" is its length, less
  65.  * the free newline. Return the status.
  66.  * Check only at the newline.
  67.  */
  68. ffputline(buf, nbuf)
  69. register char    buf[];
  70. {
  71.     register int    i;
  72.  
  73.     for (i=0; i<nbuf; ++i)
  74.         putc(buf[i]&0xFF, ffp);
  75.     putc('\r', ffp);    /* MSDOS wants \r\n line seperators */
  76.     putc('\n', ffp);
  77.     if (ferror(ffp) != FALSE) {
  78.         ewprintf("Write I/O error");
  79.         return (FIOERR);
  80.     }
  81.     return (FIOSUC);
  82. }
  83.  
  84. /*
  85.  * Write a buffer to the already
  86.  * opened file. bp points to the
  87.  * buffer. Return the status.
  88.  * Check only at the newline and
  89.  * end of buffer.
  90.  */
  91. ffputbuf(bp)
  92. BUFFER *bp;
  93. {
  94.     register char *cp;
  95.     register char *cpend;
  96.     register LINE *lp;
  97.     register LINE *lpend;
  98.  
  99.     lpend = bp->b_linep;
  100.     lp = lforw(lpend);
  101.     do {
  102.     cp = <ext(lp)[0];        /* begining of line    */
  103.     cpend = &cp[llength(lp)];    /* end of line        */
  104.     while(cp != cpend) {
  105.         putc(*cp, ffp);
  106.         cp++;    /* putc may evalualte arguments more than once */
  107.     }
  108.     lp = lforw(lp);
  109.     if(lp == lpend) break;        /* no implied newline on last line */
  110.     putc('\r', ffp);    /* MSDOS wants \r\n line seperators */
  111.     putc('\n', ffp);
  112.     } while(!ferror(ffp));
  113.     if(ferror(ffp)) {
  114.     ewprintf("Write I/O error");
  115.     return FIOERR;
  116.     }
  117.     return FIOSUC;
  118. }
  119.  
  120. /*
  121.  * Read a line from a file, and store the bytes
  122.  * in the supplied buffer. Stop on end of file or end of
  123.  * line. Don't get upset by files that don't have an end of
  124.  * line on the last line; this seem to be common on CP/M-86 and
  125.  * MS-DOS.  Delete any CR followed by a NL:  This is the normal
  126.  * format for MS_DOS files, but also occurs when files are transferred
  127.  * from VMS or MS-DOS to Unix.
  128.  */
  129. ffgetline(buf, nbuf, nbytes)
  130. register char    buf[];
  131. register int    *nbytes;
  132. {
  133.     register int    c;
  134.     register int    i;
  135.  
  136.     i = 0;
  137.     for (;;) {
  138.         c = getc(ffp);
  139. rescan:
  140.         if (c == '\r') {        /* Delete any non-stray    */
  141.             c = getc(ffp);        /* carriage returns.    */
  142.             if (c != '\n') {
  143.                 buf[i++] = '\r';
  144.                 if (i >= nbuf) return FIOLONG;
  145.                 goto rescan;
  146.             }
  147.         }
  148.         if (c==EOF || c=='\n')        /* End of line.        */
  149.             break;
  150.         buf[i++] = c;
  151.         if (i >= nbuf) return FIOLONG;
  152.     }
  153.     if (c == EOF  && ferror(ffp) != FALSE) {
  154.         ewprintf("File read error");
  155.         return FIOERR;
  156.     }
  157.     *nbytes = i;
  158.     return c==EOF ? FIOEOF : FIOSUC;
  159. }
  160.  
  161. #ifndef    NO_BACKUP
  162. /*
  163.  * Rename the file "fname" into a backup copy.
  164.  * On Unix the backup has the same name as the
  165.  * original file, with a "~" on the end - unfortunately
  166.  * this does not map well to MS-DOS - the old .bak convention
  167.  * is used.
  168.  */
  169. fbackupfile(fname)
  170. char    *fname;
  171. {
  172.     register char    *nname, *ptr;
  173.     char *strchr();
  174.  
  175.     if ((nname=malloc(strlen(fname)+3+1)) == NULL)
  176.         return (ABORT);
  177.     (void) strcpy(nname, fname);
  178.     if ((ptr = strchr(nname, '.')) != 0)
  179.         strcpy(ptr, ".bak");
  180.     else
  181.         strcat(ptr, ".bak");
  182.  
  183.     if (strcmp(fname, nname) == 0) {
  184.         free(nname);
  185.         return FALSE;
  186.     }
  187.  
  188.     (void) unlink(nname);        /* Ignore errors.    */
  189.     (void) rename(fname, nname);
  190.     free(nname);
  191.     return (TRUE);
  192. }
  193. #endif
  194.  
  195. /*
  196.  * The string "fn" is a file name.
  197.  * convert all filenames to lower case, and convert all '\\' characters
  198.  * to forward slashes.  This is simply my preference, uppercase and
  199.  * back slashes are also viable.
  200.  */
  201. /*ARGSUSED*/
  202. adjustmsdos(fn)
  203. register char    *fn;
  204. {
  205.     register char c;
  206.  
  207.     while ((c = *fn) != '\0') {
  208.         if (ISUPPER(c))
  209.             *fn = TOLOWER(c);
  210.         if (c=='/')
  211.             *fn = '\\';
  212.         ++fn;
  213.     }
  214. }
  215.  
  216.  
  217.  
  218. #ifndef    NO_STARTUP
  219. #define STARTUPNAME ".mg"
  220. /*
  221.  * find the users startup file, and return it's name. Check for
  222.  * if MGSTARTUP is defined, then use that.   Otherwise, look
  223.  * for .mg in the current directory, then in the root directory.
  224.  */
  225. char *
  226. startupfile() 
  227. {
  228.     register char    *file;
  229.     static char    temp[NFILEN];
  230.     char        *getenv();
  231.  
  232.     if ((file = getenv("MGSTARTUP")) != NULL )
  233.         {
  234.         if (access(file, F_OK) == 0)
  235.             return file;
  236.         return NULL;
  237.         }
  238.     if (access (STARTUPNAME, F_OK) == 0)
  239.         return STARTUPNAME;
  240.     strcpy(temp, "/");
  241.     strcat(temp, STARTUPNAME);
  242.     if (access (temp, F_OK) == 0)
  243.         return temp;
  244.     return NULL;
  245. }
  246. #endif
  247.  
  248. /*******************************************************************/
  249. /* new stuff between release 1a and 2a                             */
  250. /*******************************************************************/
  251.  
  252. /* convert all filenames to a canonical format, which in the case of
  253.  * MSDOS is X:/currentdir/filename.  Note that each drive letter has
  254.  * it's OWN current directory, so if the user specifies a drive letter,
  255.  * we use that drive's current directory, not it's root.
  256.  */
  257.  
  258. /* MSC doesn't have getdrive and getcurdir routines; simulate them. 
  259.  * They are both pretty gross.  Blame Microsoft */
  260.  
  261. #ifdef MSC
  262. unsigned getdisk()
  263. {
  264.     unsigned currentdrive;
  265.  
  266.     _dos_getdrive(¤tdrive);
  267.     return currentdrive-1;
  268. }
  269.  
  270. void getcurdir(unsigned drivenumber, char *buf)
  271. {
  272.     unsigned currentdrive = getdisk()+1;
  273.     unsigned number_of_drives;        /* unused */
  274.     static char bufr[NFILEN];
  275.  
  276.     _dos_setdrive(drivenumber, &number_of_drives);
  277.     getcwd(&bufr[0], NFILEN-1);
  278.     _dos_setdrive(currentdrive, &number_of_drives);
  279.     strcpy(buf, &bufr[3]);
  280. }
  281. #endif
  282.  
  283. char *adjustname(fn)
  284. register char *fn;
  285. {
  286.     register char *cp;
  287.     static char fnb[NFILEN];
  288.     struct passwd *pwent;
  289.  
  290.     cp = fnb;
  291.     /* handle A:foo\bar */
  292.     if (fn[0] && fn[1] == ':') {
  293.     *cp++ = *fn++;
  294.     *cp++ = *fn++;
  295.     *cp = '\0';
  296.     adjustmsdos(fnb);    /* force case to lower */
  297.     if (*fn != '/' && *fn != '\\') {
  298.         *cp++ = '\\';
  299.         getcurdir(fnb[0]-'a'+1, cp);
  300.         cp = fnb + strlen(fnb);
  301.     }
  302.     else
  303.         *cp++ = *fn++;
  304.     }
  305.     /* handle \foo\bar */
  306.     else if (*fn == '/' || *fn == '\\') {
  307.     *cp++ = (char) (getdisk() + 'a');
  308.     *cp++ = ':';
  309.     *cp++ = *fn++;
  310.     }
  311.     else {
  312.     strcpy(fnb, wdir);
  313.     cp = fnb + strlen(fnb);
  314.     }
  315.  
  316.     if(cp != fnb && cp[-1] != '/' && cp[-1] != '\\') *cp++ = '\\';
  317.  
  318.     /* at this point, we should have a drive, and at least a single */
  319.     /* slash.  Now copy over the rest of the filename, while handling */
  320.     /* certain pathalogical cases */
  321.  
  322.     /* convert "//" to "/", "/./" to "/", and "/x/../" to "/" */
  323.     while(*fn) {
  324.         switch(*fn) {
  325.         case '.':
  326.         switch(fn[1]) {
  327.                 case '\0':
  328.                 *--cp = '\0';
  329.             adjustmsdos(fnb);
  330.                 return fnb;
  331.                 case '/':
  332.             case '\\':
  333.                     fn += 2;
  334.                 continue;
  335.             case '.':
  336.                 if(fn[2]=='/' || fn[2]=='\\' || fn[2] == '\0') {
  337.                 --cp;
  338.                 while(cp > fnb && *--cp != '/' && *cp != '\\')
  339.                 ;
  340.                 if (cp==fnb) cp += 2;
  341.                 ++cp;
  342.                 if(fn[2]=='\0') {
  343.                     *--cp = '\0';
  344.                 adjustmsdos(fnb);
  345.                     return fnb;
  346.                 }
  347.                     fn += 3;
  348.                     continue;
  349.                 }
  350.                 break;
  351.             default:
  352.                 break;
  353.             }
  354.         break;
  355.         case '/':
  356.         case '\\':
  357.             fn++;
  358.             continue;
  359.         default:
  360.             break;
  361.     }
  362.     while(*fn && (*cp++ = *fn++) != '/' && fn[-1] != '\\')
  363.         ;
  364.     }
  365.     if (cp != fnb + 3 && cp[-1]=='\\') --cp;
  366.     *cp = '\0';
  367.     adjustmsdos(fnb);
  368.     return fnb;
  369. }
  370.  
  371. #ifndef NO_DIRED
  372. #include "kbd.h"
  373. #define DIRFILE "_dirlist_.$$$"
  374.  
  375. BUFFER *dired_(dirname)
  376. char *dirname;
  377. {
  378.     register BUFFER *bp;
  379.     char line[256];
  380.     BUFFER *findbuffer();
  381.     char *strncpy();
  382.     int i;
  383.  
  384.     if((dirname = adjustname(dirname)) == NULL) {
  385.     ewprintf("Bad directory name");
  386.     return NULL;
  387.     }
  388.     if((bp = findbuffer(dirname)) == NULL) {
  389.     ewprintf("Could not create buffer");
  390.     return NULL;
  391.     }
  392.     if(bclear(bp) != TRUE) return FALSE;
  393.     (VOID) strcpy(line, "dir ");
  394.     (VOID) strcat(line, dirname);
  395.     (VOID) strcat(line, " > ");
  396.     (VOID) strcat(line, DIRFILE);
  397.     system(line);
  398.     if (ffropen(DIRFILE) != FIOSUC) {
  399.      ewprintf("Can't open temporary dir file");
  400.      return NULL;
  401.     }
  402.     line[0] = line[1] = ' ';
  403.     if (ffgetline(&line[2], sizeof(line)-3, &i) != FIOSUC) {
  404.     ffclose();
  405.     (void)unlink(DIRFILE);
  406.     ewprintf("No such directory: `%s'", dirname);
  407.         return NULL;
  408.     }
  409.     while (ffgetline(&line[2], sizeof(line)-3, &i) == FIOSUC) {
  410.     line[i+2] = '\0';
  411.     (VOID) addline(bp, line);
  412.     }
  413.     ffclose();
  414.     (void)unlink(DIRFILE);
  415.  
  416.     bp->b_dotp = lforw(bp->b_linep);        /* go to first line */
  417.     (VOID) strncpy(bp->b_fname, dirname, NFILEN);
  418.     if((bp->b_modes[0] = name_mode("dired")) == NULL) {
  419.     bp->b_modes[0] = &map_table[0];
  420.     ewprintf("Could not find mode dired");
  421.     return NULL;
  422.     }
  423.     bp->b_nmodes = 0;
  424.     return bp;
  425. }
  426.  
  427. /* this is really ugly, but then so was the UNIX version! */
  428. #define BASENAME 2
  429. #define EXT    11
  430. #define DIR    15
  431. d_makename(lp, fn)
  432. register LINE *lp;
  433. register char *fn;
  434. {
  435.     register char *cp;
  436.     register char *last;
  437.     int len;
  438.     extern char *strchr();
  439.  
  440.     if(llength(lp) != 41) return ABORT;
  441.     if(lgetc(lp,BASENAME) == ' ') return ABORT;
  442.     if(lgetc(lp,EXT-1) != ' ') return ABORT;
  443.     (VOID) strcpy(fn, curbp->b_fname);
  444.     cp = fn + strlen(fn);
  445.     if ((cp[-1] != '\\') && (cp[-1] != '/'))    /* append '/' if needed    */
  446.     *cp++ = '\\';
  447.     if ((last = strchr(lp->l_text+BASENAME, ' ')) == 0) return ABORT;
  448.     len = last - (lp->l_text+BASENAME);
  449.     bcopy(lp->l_text+BASENAME, cp, len);
  450.     cp += len;
  451.     if ((last = strchr(lp->l_text+EXT, ' ')) == 0) return ABORT;
  452.     len = last - (lp->l_text+EXT);
  453.     if (len != 0) {
  454.     *cp++ = '.';
  455.     bcopy(lp->l_text+EXT, cp, len);
  456.     }
  457.     cp[len] = '\0';
  458.     return (strncmp(lp->l_text+DIR, "<DIR>", 5) == 0);
  459. }
  460.  
  461. /* sorry, this is a hack - jpn */
  462. /* I should probably fix this */
  463. copy(frname, toname)
  464. char *frname, *toname;
  465. {
  466.     char buffer[512];
  467.     int pid;
  468.     int status;
  469.     char cmdbuf[80];
  470.  
  471.     sprintf(cmdbuf, "Copy %s %s", frname, toname);
  472.     system(cmdbuf);
  473.     return TRUE;
  474. }
  475.  
  476. unlinkdir(f)
  477. char *f;
  478. {
  479.     return (rmdir(f));
  480. }
  481.  
  482. #endif /* NO_DIRED */
  483.